# +----------------------------------------------------------------------
# | ChatWork
# +----------------------------------------------------------------------
# | 这不是一个自由软件,您只能在不用于商业目的的前提下对程序代码进行修改和使用。
# | 任何企业和个人不允许对程序代码以任何形式任何目的再发布,商业使用请获取授权。
# +----------------------------------------------------------------------
# | Author: ChatWork Team <2474369941@qq.com>
# +----------------------------------------------------------------------
import time
from typing import List
from exception import AppException
from common.utils.urls import UrlUtil
from common.utils.times import TimeUtil
from common.enums.agent import AgentEnum
from common.models.users import UserModel
from common.models.agents import AgentMcpModel
from common.models.agents import AgentMcpTeamedModel
from apps.api.schemas.agent.mcp import teamed_schema as schema


class McpTeamedService:
    """ MCP团队服务类 """

    POWER_VIEW = AgentEnum.POWER_VIEW    # 查看者
    POWER_EDIT = AgentEnum.POWER_EDIT    # 编辑者
    POWER_ADMIN = AgentEnum.POWER_ADMIN  # 管理者
    POWER_OWNED = AgentEnum.POWER_OWNED  # 拥有者

    @classmethod
    async def find_user(cls, params: schema.McpTeamedSearchIn) -> schema.McpTeamedUserVo:
        """
        MCP成员查找。

        Args:
            params (schema.McpTeamedSearchIn): 成员搜索参数。

        Returns:
            List[schema.McpTeamedUserVo]: 当前用户的权限。

        Author:
            zero
        """
        if not params.keyword:
            raise AppException(str("请输入需查找的用户编号!"))

        user = await UserModel.filter(sn=params.keyword).first()
        if user is None:
            raise AppException("搜索不到该用户，请输入正确的用户编号!")

        mcp = await AgentMcpModel.filter(code=params.ap_code, is_delete=0).first()
        if mcp is None:
            raise AppException("mcp已不存在，请刷新页面再重试吧!")

        if mcp.user_id == user.id:
            raise AppException("该用户是本团队管理员，请务重复绑定!")

        member = await AgentMcpTeamedModel.filter(mcp_id=mcp.id, user_id=user.id).first()
        if member:
            raise AppException("该用户是本团队的成员，无需重复绑定!")

        return schema.McpTeamedUserVo(
            sn=user.sn,
            nickname=user.nickname,
            avatar=await UrlUtil.to_absolute_url(user.avatar)
        )

    @classmethod
    async def lists(cls, user_id: int, params: schema.McpTeamedSearchIn) -> List[schema.McpTeamedListVo]:
        """
        MCP成员列表。

        Args:
            user_id (int): 用户ID
            params (schema.McpTeamedSearchIn): 成员搜索参数。

        Returns:
            List[schema.McpTeamedListVo]: 当前用户的权限。

        Author:
            zero
        """
        # 验证MCP
        mcp = await AgentMcpModel.filter(code=params.ap_code, is_delete=0).first()
        if mcp is None:
            raise AppException("MCP不存在!")

        # 验证权限
        if mcp.user_id != user_id:
            await cls.has_permission(mcp.code, user_id, cls.POWER_VIEW)

        # 查询团队
        lists = await AgentMcpTeamedModel.filter(mcp_id=int(mcp.id)).all()

        # 提取用户ID
        user_ids = [item.user_id for item in lists if item.user_id]
        users = await UserModel.queryUserDictsById(user_ids)

        _lists = []

        # MCP拥有者
        owned = await UserModel.filter(id=int(mcp.user_id)).first()
        _lists.append(schema.McpTeamedListVo(
            id=0,
            user_sn=owned.sn,
            user_avatar=await UrlUtil.to_absolute_url(owned.avatar),
            user_nickname=owned.nickname,
            power=cls.POWER_OWNED,
            create_time=TimeUtil.timestamp_to_date(owned.create_time),
            update_time=TimeUtil.timestamp_to_date(owned.update_time)
        ))

        # MCP协作者
        for item in lists:
            user = users.get(item.user_id, {})
            _lists.append(schema.McpTeamedListVo(
                id=item.id,
                power=item.power,
                user_sn=user.get("sn", ""),
                user_avatar=await UrlUtil.to_absolute_url(user.get("avatar", "")),
                user_nickname=user.get("nickname", ""),
                create_time=TimeUtil.timestamp_to_date(item.create_time),
                update_time=TimeUtil.timestamp_to_date(item.update_time)
            ))

        return _lists

    @classmethod
    async def add(cls, user_id: int, post: schema.McpTeamedAddIn) -> None:
        """
        MCP成员添加。

        Args:
            user_id (str): 操作用户ID。
            post (schema.McpTeamedAddIn): 添加参数。

        Author:
            zero
        """
        # 验MCP
        mcp = await AgentMcpModel.filter(code=post.ap_code, is_delete=0).first()
        if mcp is None:
            raise AppException("MCP不存在!")
        if mcp.is_disable:
            raise AppException("MCP已禁用!")

        # 验证用户
        user = await UserModel.filter(sn=post.user_sn).first()
        if user is None:
            raise AppException("用户不存在!")
        if user.is_disable == int(1):
            raise AppException("用户被限制!")

        # 验证成员
        member = await AgentMcpTeamedModel.filter(mcp_id=mcp.id, user_id=user.id).first()
        if member or mcp.user_id == user.id:
            raise AppException("用户已存在团队中了!")

        # 如果不是拥有者 并且 需要添加管理员
        if mcp.user_id != user_id and post.power == cls.POWER_ADMIN:
            # 验证添加的权限
            if post.power == cls.POWER_ADMIN:
                raise AppException("抱歉了,添加管理员需MCP拥有者操作!")
            # 验证操作的权限
            my = await AgentMcpTeamedModel.filter(mcp_id=mcp.id, user_id=user_id).first()
            if my is None or my.power != cls.POWER_ADMIN:
                raise AppException("抱歉了,您不具备添加成员的操作权限!")

        # 添加到团队中
        await AgentMcpTeamedModel.create(
            mcp_id=mcp.id,
            user_id=user.id,
            power=post.power,
            create_time=int(time.time()),
            update_time=int(time.time())
        )

    @classmethod
    async def edit(cls, user_id: int, post: schema.McpTeamedEditIn) -> None:
        """
        MCP成员编辑。

        Args:
            user_id (str): 操作用户ID。
            post (schema.McpTeamedEditIn): 编辑参数。

        Author:
            zero
        """
        # 验证成员
        teamed = await AgentMcpTeamedModel.filter(id=post.id).first()
        if teamed is None:
            raise AppException("成员记录不存在!")

        # 验MCP
        mcp = await AgentMcpModel.filter(id=teamed.mcp_id, is_delete=0).first()
        if mcp is None:
            raise AppException("MCP不存在!")
        if mcp.is_disable:
            raise AppException("MCP已禁用!")

        # 如果不是MCP拥有者
        if mcp.user_id != user_id:
            # 验证是否是管理员
            my = await AgentMcpTeamedModel.filter(mcp_id=mcp.id, user_id=user_id).first()
            if int(my.power) != cls.POWER_ADMIN:
                raise AppException("抱歉了,该操作仅管理员可用!")
            # 如果数据是管理员
            if teamed.power == cls.POWER_ADMIN:
                raise AppException("抱歉了,您无权限修改管理员!")

        # 自己不能修改自己
        if teamed.user_id == user_id:
            raise AppException("抱歉了,您不能修改自己权限!")

        # 更新权限信息
        await AgentMcpTeamedModel.filter(id=post.id).update(
            power=post.power,
            update_time=int(time.time())
        )

    @classmethod
    async def exits(cls, user_id: int, ap_code: str) -> None:
        """
        MCP成员退出。

        Args:
            user_id (str): 操作用户ID。
            ap_code (str): MCP编号。

        Author:
            zero
        """
        # 验MCP
        mcp = await AgentMcpModel.filter(code=ap_code, is_delete=0).first()
        if mcp is None:
            raise AppException("MCP不存在!")
        if mcp.is_disable:
            raise AppException("MCP已禁用!")

        # 验证成员
        teamed = await AgentMcpTeamedModel.filter(user_id=user_id, mcp_id=mcp.id).first()
        if teamed is None:
            raise AppException("您不是团队成员!")

        # 移除成员
        await AgentMcpTeamedModel.filter(id=teamed.id).delete()

    @classmethod
    async def delete(cls, user_id: int, id_: int) -> None:
        """
        MCP成员删除。

        Args:
            user_id (str): 操作用户ID。
            id_ (int): 成员ID。

        Author:
            zero
        """
        # 验证成员
        teamed = await AgentMcpTeamedModel.filter(id=id_).first()
        if teamed is None:
            raise AppException("成员记录不存在!")

        # 验MCP
        mcp = await AgentMcpModel.filter(id=teamed.mcp_id, is_delete=0).first()
        if mcp is None:
            raise AppException("MCP不存在!")
        if mcp.is_disable:
            raise AppException("MCP已禁用!")

        # 如果不是MCP拥有者
        if mcp.user_id != int(user_id):
            # 验证是否是管理员
            my = await AgentMcpTeamedModel.filter(mcp_id=mcp.id, user_id=user_id).first()
            if my.power != cls.POWER_ADMIN:
                raise AppException("抱歉,该操作仅管理员可用!")
            # 如果数据是管理员
            if teamed.power == cls.POWER_ADMIN:
                raise AppException("抱歉,您无权限删除管理员!")

        # 自己不能修改自己
        if teamed.user_id == user_id:
            raise AppException("抱歉,您不能自己删除自己哦!")

        # 删除成员
        await AgentMcpTeamedModel.filter(id=id_).delete()

    @classmethod
    async def has_permission(cls, code: str, user_id: int, power: int = None) -> int:
        """
        验证用户权限。

        Args:
            code (str): MCP编号。
            user_id (str): 用户ID。
            power (str): 最低权限: [1=查看权, 2=编辑权, 3=管理权, 4=所有权]。

        Returns:
            power (int): 当前用户的权限。

        Author:
            zero
        """
        if power is None:
            power = cls.POWER_ADMIN

        mcp = await AgentMcpModel.filter(code=code).first().values("id", "code", "user_id", "create_time")
        if int(mcp["user_id"]) == user_id:
            return cls.POWER_OWNED

        member = await AgentMcpTeamedModel.filter(mcp_id=mcp["id"], user_id=user_id).first()
        if member is None:
            raise AppException(str("非法操作,您不是该MCP团队成员!"))

        if member.power < power:
            enums = {1: "查看权", 2: "编辑权", 3: "管理权", 4: "拥有权"}
            raise AppException("您无权限操作, 所需权限 ["+enums[power]+"]")

        return member.power
